#include "precompiled.h"
#include "feralcombat.h"
using namespace std;
using namespace weo::engine::item;
using namespace weo::engine::character::druid;

Combat::Combat()
{
    Meleedps::Init();
    Equipcom::UseWeaponProcs(false);
    m_Classnr = weo::engine::character::Character::isAllowed("Druid");
    m_Basevalues.push_back(Attribute("Agility",66));
    m_Basevalues.push_back(Attribute("Intellect",142));
    m_Basevalues.push_back(Attribute("Strength",83));
    m_Basevalues.push_back(Attribute("Stamina",87));
    m_Basevalues.push_back(Attribute("Spirit",139));
    m_Basevalues.push_back(Attribute("CritRating",0.8f*CritRating)); // crit
    m_Basevalues.push_back(Attribute("AttackPower",120)); // ap
    m_Basevalues.push_back(Attribute("Health",3434)); // health
    // talents
    m_Basevalues.push_back(Attribute("AttackPower",140)); // ap
    m_Basevalues.push_back(Attribute("ArmorPenetration",610)); // faerie fire
    m_Basevalues.push_back(Attribute("AttackPower",1.5f*70)); // ap
    m_Basevalues.push_back(Attribute("CritRating",6*CritRating)); // cr
    m_Equip.Mode(0);
    BOOST_FOREACH(Attribute attr, m_Basevalues)
    {
        handleAttribute(attr);
    }
    // base settings finished
}
float Combat::evaluateTF()
{
    //mangle, shred up to 5cp, rip
    float wdps = m_Equip[46];
    float ap = m_Equip[30] + m_Equip[37];
    float crit = m_Equip[6]/CritRating;
    float hit = min<float>(100 - 9 + m_Equip[7]/HitRating, 100);
    float dodge = 6.5f - (m_Equip[51]/ExpertiseRating) * 0.25f;
    float haste = m_Equip[10]/HasteRating;
    // -- glancing blow calculation -- //
    float glancingreduction = 25;
    float glancingprob = 25;
    float glancing = glancingreduction * glancingprob / 100;
    float shredcount = (4 - 4*(crit / 100.0f)); // we already have one cp from mangle
    float calchaste = (1 + haste / 100); // +snd + haste + bladeflurry
    float mangleenergy = 40;
    float ripenergy  = 32;
    if(m_Equip.hasSpecial(337532))
    {
        mangleenergy -= 5;
    }
    mangleenergy = 0.2f*mangleenergy + 0.8f*(hit-dodge)*(1/100.0f)*mangleenergy;
    ripenergy = 0.2f*ripenergy + 0.8f*(hit-dodge)*(1/100.0f)*ripenergy;;
    float rotenergy = mangleenergy + 42.0f * shredcount + ripenergy;
    float avgenergy = rotenergy / (2 + shredcount);
    float rottime = rotenergy / 10.0f;
    rottime -= ((rottime / 60.0f) * 2.0f * (avgenergy / 10.0f)); // crude inclusion omen of clarity, two omen procs, 0.5 procs per rotation, so basically around 2s less rotation time
    float shredadd = 405;
    if(m_Equip.hasSpecial(881117))
    {
        shredadd += 88;
    }
    float whitedmg = wdps + ap / 14.0f;
    float whitedps = (1/100.0f) * calchaste * (hit - dodge - glancing + crit*1.1f) * whitedmg;
    float mangledmg = 1.2f * (1/100.0f) * (hit - dodge + crit*1.1f) * (1.6f * whitedmg + 325);
    float shreddmg = 1.3f * (1/100.0f) * (hit - dodge + crit*1.1f) * (2.25f * whitedmg + shredadd);
    float ripdmg = 1.3f * (1554 + 0.24f * ap);
    if(m_Equip.hasSpecial(927501))
    {
        ripdmg *= 1.15f;
    }
    float armorreduction = max<float>((MobArmor - m_Equip[50])/(MobArmor - m_Equip[50] + 10557.5f),0);
    float finaldps =  1.1f *((1.0f-armorreduction) * (whitedps + (mangledmg + shredcount * shreddmg)/rottime) + ripdmg/rottime); // sum it up and divide by rottime if appropriate
    return m_CondFactor * finaldps;
}
void Combat::filterEquip(std::vector<std::vector<const weo::engine::item::Item*>>& items)
{
    for(unsigned int i = 0;i<10;i++)
    {
        int subtype = 3;
        if(i == 1 || i == 3)
        {
            items.push_back(m_Database->getPtrbyType(1,i+1));
        }
        else
        {	
            items.push_back(m_Database->getPtrbyType(1,i+1,2));
        }
    }
    items.push_back(m_Database->getPtrbyType(2,0));
    items.push_back(m_Database->getPtrbyType(2,0));
    items.push_back(m_Database->getPtrbyType(3,0));
    items.push_back(m_Database->getPtrbyType(3,0));
    // staff
    vector<const Item*> staff = m_Database->getPtrbyType(4,4,6);
    //offhand empty
    vector<const Item*> offhand;
    offhand.push_back(Item::None());
    items.push_back(staff);
    items.push_back(offhand);
    items.push_back(m_Database->getPtrbyType(4,5,17)); // relicts
    items.push_back(m_Database->getPtrbyType(5,0));
    Meleedps::filterEquip(items);
}
void Combat::handleAttribute(const Attribute& attr)
{
    switch(attr.Type())
    {
    case 1:
    case 3:
    case 4:
    case 5:
        Meleedps::handleAttribute(Attribute(attr.Type(),attr.Value() * 1.03f));
        break;
    case 2:
        Meleedps::handleAttribute(Attribute(attr.Type(),attr.Value() * 1.03f * 1.2f));
        break;
    case 30:
        Meleedps::handleAttribute(Attribute(attr.Type(),attr.Value() * 1.1f));
        break;
    default:
        Meleedps::handleAttribute(attr);
        break;
    }
}